package pro.cherish.smartfile.config.aspect;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import pro.cherish.smartfile.common.constant.CommonConstants;
import pro.cherish.smartfile.config.AppContext;

/**
 * @author 创建人：lys
 * @version 版本号：V1.0
 * <p>
 * ***************************修订记录************************************
 * 2020-6-3 lys 创建该类功能。
 * **********************************************************************
 * </p>
 * @ClassName 类名：WebLogAcpect
 * @Description 功能说明：WEB接口切面
 * <p>
 * 实现打印日志：
 * 1、接口地址
 * 2、接口HTTP方法
 * 3、接口参数
 * </p>
 * **********************************************************************
 * @date 创建日期： 2020-6-3
 */
@Aspect
@Component
@Slf4j
public class WebLogAspect {
    /**
     * 切入点为pro.cherish.smartfile.rest包（包含子包）下的所有类的所有接口方法（标志了@PostMapping和@GetMapping注解）
     */
    @Pointcut("execution(public * pro.cherish.smartfile.rest..*.*(..)) && ( @annotation(org.springframework.web.bind.annotation.PostMapping)|| @annotation(org.springframework.web.bind.annotation.GetMapping))")
    public void webLog() {

    }


    /**
     * 环绕通知，异常不处理，直接抛出，由各自接口处理，如果接口不处理则在exception.JsonErrorWebExceptionHandler#getErrorAttributes(org.springframework.web.reactive.function.server.ServerRequest, boolean)统一处理了
     *
     * @param proceedingJoinPoint
     * @Return java.lang.Object
     * @Author lys
     * @Date 2020-6-3 14:38
     */
    @Around(value = "webLog()")
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String traceId = "无";
        if (ObjectUtil.isNotNull(AppContext.getLocal(CommonConstants.SYS_TRACE_ID))) {
            traceId = AppContext.getLocal(CommonConstants.SYS_TRACE_ID);
        }
        Object result;
        String msg;
        String controllerMethodName = proceedingJoinPoint.getSignature().getDeclaringTypeName();
        if (ObjectUtil.isNotNull(AppContext.getLocal(CommonConstants.SERVER_EXCHANGE))) {
            ServerWebExchange serverWebExchange = AppContext.getLocal(CommonConstants.SERVER_EXCHANGE);
            ServerHttpRequest request = serverWebExchange.getRequest();
            msg = StrUtil.format("sysTraceId={},请求路径={},HTTP方法名={},接口名={},方法名={}\n", traceId, request.getPath(), request.getMethodValue(), controllerMethodName, proceedingJoinPoint.getSignature().getName());
            log.info(msg);
            //判断请求是什么请求
            Object[] args = proceedingJoinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                if (ObjectUtil.isNotNull(args[i])) {
                    Class<?> aClass = args[i].getClass();
                    String argJsonStr = JSONObject.toJSONString(args[i]);
                    log.info("sysTraceId={},AOP切面拦截的参数[{}],参数类型={}，参数值={}", traceId, i + 1, aClass, argJsonStr);
                }
            }
        }
        result = proceedingJoinPoint.proceed();
        return result;
    }
}
